package com.frinder.robot.handler;

import akka.actor.ActorSelection;
import com.frinder.base.akka.AbstractRequest;
import com.frinder.robot.handler.RobotTaskManagerActor.ApplyForRobotTaskPayload;
import com.frinder.robot.handler.task.RobotTask;
import com.frinder.robot.handler.wrapper.RobotWrapper;
import com.frinder.robot.task.BaseRobotTask;
import lombok.Builder;
import lombok.Setter;
import lombok.ToString;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @ClassName RobotActor
 * @Description 机器人服务类
 * @Author frinder
 * @Date 2019/9/30 14:16
 * @Verion 1.0
 */
@Component
@Scope("prototype")
public class RobotTaskActor extends BaseRobotActor {

    public static final String NAME = "robot-task-actor-%s";

    private final ActorSelection robotTaskManagerActor;

    private final RobotWrapper wrapper;

    public RobotTaskActor(String robotName, ActorSelection robotTaskManagerActor) {
        super(robotName);
        this.robotTaskManagerActor = robotTaskManagerActor;
        this.wrapper = new RobotWrapper(robotName);
        // 延迟30s，申请任务
        applyForTask(10 * 1000);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                // 申请机器人任务
                .match(ApplyForRobotTaskPayload.class, this::applyForTask)
                // 接收机器人任务
                .match(ReceiveTaskPayload.class, this::receive)
                // 开始执行机器人任务
                .match(DoTaskPayload.class, this::doTask)
                // 完成机器人任务行
                .match(DoneTaskPayload.class, this::doneTask)
                // 完成机器人任务
                .match(CompletedTaskPayload.class, this::completedTask)
                .build();
    }

    /**
     * 完成任务
     *
     * @param payload
     */
    private void completedTask(CompletedTaskPayload payload) {
        log.info("CompletedTaskPayload: {}", payload);
        wrapper.getTask().ifPresent(task -> {
            if (task.hasNext()) {
                // 存在子任务，则继续执行
                applyDoTask(500);
            } else {
                // 子任务全部完成，则清空当前任务
                wrapper.clearTask();
                // 任务完成，申请新任务
                applyForTask(1000);
            }
        });
    }

    /**
     * 完成任务行
     *
     * @param payload
     */
    private void doneTask(DoneTaskPayload payload) {
        log.info("CompletedTaskPayload: {}", payload);
        wrapper.getTask().ifPresent(task -> {
            if (task.hasNext()) {
                BaseRobotTask pollTask = task.poll();
                log.info("完成任务：{}", pollTask);
                // 申请执行任务
                applyDoTask(500);
            } else {
                // 申请完成任务
                applyCompleteTask(500);
            }
        });
    }

    /**
     * 开始执行任务
     *
     * @param payload
     */
    private void doTask(DoTaskPayload payload) {
        log.info("DoTaskPayload: {}", payload);
        wrapper.getTask().ifPresent(task -> {
            if (task.hasNext()) {
                // 存在任务，则执行
                // todo
                BaseRobotTask peekTask = task.peek();
                log.info("{}", peekTask);
            } else {
                // 所有任务执行完成则清空任务头
                wrapper.clearTask();
                // 申请任务
                applyForTask(1000);
            }
        });
    }

    /**
     * 接收任务
     *
     * @param payload
     */
    private void receive(ReceiveTaskPayload payload) {
        log.info("ReceiveTaskPayload: {}", payload);
        // 任务为空才添加任务
        if (wrapper.emptyTask()) {
            // 设置机器人任务
            wrapper.addTask(payload.task);
            // 申请执行任务
            applyDoTask(500);
        } else {
            log.warn("已存在机器人任务：{}", wrapper.getTask());
        }
    }

    /**
     * 申请任务
     *
     * @param payload
     */
    private void applyForTask(ApplyForRobotTaskPayload payload) {
        log.info("Once: {}", payload);
        if (wrapper.emptyTask()) {
            // 任务不存在，则申请任务
            this.robotTaskManagerActor.tell(payload, getSelf());
        } else {
            // 已存在任务，则不处理
            log.info("机器人执行任务中，请稍候……");
        }
    }

    /**
     * 申请完成任务
     *
     * @param interval
     */
    private void applyCompleteTask(int interval) {
        scheduleOnce(CompletedTaskPayload.builder().build(), interval);
    }

    /**
     * 申请执行任务
     *
     * @param interval
     */
    private void applyDoTask(int interval) {
        scheduleOnce(DoTaskPayload.builder().build(), interval);
    }

    /**
     * 申请机器人任务
     */
    private void applyForTask(int interval) {
        scheduleOnce(ApplyForRobotTaskPayload.builder().build(), interval);
    }

    /**
     * 完成任务请求
     */
    @ToString(callSuper = true)
    public static class CompletedTaskPayload extends AbstractRequest {
        @Builder
        private CompletedTaskPayload(String traceId) {
            super(traceId);
        }
    }

    /**
     * 完成任务行请求
     */
    @ToString(callSuper = true)
    public static class DoneTaskPayload extends AbstractRequest {
        @Builder
        private DoneTaskPayload(String traceId) {
            super(traceId);
        }
    }

    /**
     * 申请执行任务请求
     */
    @ToString(callSuper = true)
    public static class DoTaskPayload extends AbstractRequest {
        @Builder
        private DoTaskPayload(String traceId) {
            super(traceId);
        }
    }

    /**
     * 接收任务请求
     */
    @ToString(callSuper = true)
    public static class ReceiveTaskPayload extends AbstractRequest {
        @Setter
        private RobotTask task;

        @Builder
        private ReceiveTaskPayload(String traceId, RobotTask task) {
            super(traceId);
            this.task = task;
        }
    }

}
